iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0
Modern Web

Node.js 非專業解說系列 第 19

DAY19: Stream pipe()做起來!!

  • 分享至 

  • xImage
  •  

今天要接著DAY:18淺談Stream的概念,實作一些例子來解說。
在這篇的概念中有提到一個例子:文件的讀取,若是按照原來的方式的話...

var http=require("http");
var fs=require("fs");
var server=http.createServer((req,res)=>
{
    fs.readFile("./Heartbeat.txt",(err,data)=>
{
        res.end(data);
    }); 
});
server.listen(3000);

當文件內容很大時,就會消耗不少伺服器的記憶體,使用者等待的時間就會因此變長
而HTTP中的requestresponse都是屬於"流"的物流件,
request屬於可讀流response屬於可寫流
因此將上面的例子改寫成這樣:

//ReadStream
var http=require("http");
var fs=require("fs");
var readstream=require("stream");
var server=http.createServer((req,res)=>
{       
       readStream=fs.createReadStream("./Heartbeat.txt");             
       readStream.pipe(res);//將可讀流寫入response    
});
server.listen(3000);

Stream就會利用緩衝區來儲存被切割的數據來給程序讀取文件,
如此一來,文件內容大時,就不用擔心伺服器的記憶體。
pipe()會自動的調用dataend事件,也就相當於:

var buf=[];
req.on("data",(chunck)=>
{
    buf.push(chunck);
});
req.on("end",()=>
{
    buf=Buffer.concat(buf).toString();
})

另外可以使用pipe的特性將流與流之間串連起來,達到好的效用!
像是使用pipe()複製文件就相當方便!
只要將一個文件設為可讀流(readable),而把要複製過去的文件設為可寫流,接著再透過pipe來完成,
其實就像是複製貼上一樣。
首先準備兩份文件:
第一份名為butterfly.txt (摘取自蔡依林-花蝴蝶),內容為以下:

https://ithelp.ithome.com.tw/upload/images/20211001/2014024451v7hoIjjz.png

第二份名為heartbeat.txt (摘取自BTS-Heartbeat),內容為以下:
https://ithelp.ithome.com.tw/upload/images/20211001/20140244oAKMXFvUIR.png

接下來我想將butterfly.txt的內容複製到heartbeat.txt這個檔案。

//使用pipe()複製文件
var stream=require("stream");
****const fs=require("fs");
let butterfly=fs.createReadStream("./butterfly.txt");
let heartbeat=fs.createWriteStream("./heartbeat.txt");

butterfly.pipe(heartbeat);

首先導入stream模塊與fs模塊,
設定butterfly.txt為可讀流,heartbeat.txt設為可寫流。
執行結果:

https://ithelp.ithome.com.tw/upload/images/20211001/20140244kQbGD8EwvM.png

是不是覺得哪裡怪怪的,怎麼沒有執行結果…,
我也困惑了一下,但是其實執行結果已經結束了,
接著打開 heartbeat.txt 會發現裡面的內容變成了 butterfly.txt 的內容。

https://ithelp.ithome.com.tw/upload/images/20211001/20140244E38UNkuDcb.png

也可以來個混搭,設定第三份文件名為 変わらないもの.txt ,內容為:

https://ithelp.ithome.com.tw/upload/images/20211001/20140244bZNVjnwXgp.png

//使用pipe()複製文件
var stream=require("stream");
const fs=require("fs");
let butterfly=fs.createReadStream("./butterfly.txt");
let heartbeat=fs.createWriteStream("./heartbeat.txt");
let neverchange=fs.createReadStream("./変わらないもの.txt");

butterfly.pipe(heartbeat);
neverchange.pipe(heartbeat);

変わらないもの.txt設為可讀流。
執行結果:

https://ithelp.ithome.com.tw/upload/images/20211001/20140244s0VQm4Q1l8.png

https://ithelp.ithome.com.tw/upload/images/20211001/20140244g6og4xPVpV.png

https://ithelp.ithome.com.tw/upload/images/20211001/20140244FxtecTfFL3.png

可以看到,兩個設為可讀流的檔案內容依然不變,
但是設為可寫流的heartbeat.txt出現了兩個可讀流的內容!!

總結:

今天的重點就到這邊,其實感覺要交代的東西還很多,但每研讀完一篇就已經消耗了很多腦力…,
我認為在Stream中最重要的就是可寫流可讀流pipe()的運用。

另外,附上兩張很可愛的動圖,有便於直接理解pipe()的工作。
若不使用Stream(勞動仔...):

使用Stream(動感光波!!!):

動圖來源:
https://www.cnblogs.com/vajoy/p/6349817.html


上一篇
DAY18: 淺談Stream
下一篇
Day20: EventEmitter
系列文
Node.js 非專業解說30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言